﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;

namespace ACSR.Core.Processes
{
    public class MethodDocumentationAttribute : Attribute
    {
        public MethodDocumentationAttribute(string description)
        {
            this.Description = description;
        }

        public string Description { get; set; }
    }

    public static class CommandLineApplication
    {

        static string GetParameters(MethodInfo method)
        {
            var sb = new StringBuilder();
            foreach (var parameter in method.GetParameters())
            {
                if (sb.Length > 0)
                    sb.Append(", ");
                sb.Append(parameter.ParameterType.Name + " ");
                sb.Append(parameter.Name);
            }
            return "(" + sb.ToString() + ")";
        }

        static void PrintParameters(MethodInfo method)
        {
            int index = 0;
            foreach (var parameter in method.GetParameters())
            {
                Console.ForegroundColor = ConsoleColor.DarkGray;
                if (index > 0)
                    Console.Write(", ");
                Console.Write(parameter.ParameterType.Name);
                Console.Write(" ");
                Console.ForegroundColor = ConsoleColor.Magenta;
                Console.Write(parameter.Name);
                index++;
            }
        }

        public static void Run(ICommandController controller)
        {
            var cmd = new CmdLineHelper(true);
            string commandName = null;
            if (cmd.Args.Count > 1)
                commandName = cmd.Args[1];

            if (string.IsNullOrEmpty(commandName))
            {
                foreach (var method in controller.GetType().GetMethods().OrderBy(methi => methi.Name))
                {
                    foreach (MethodDocumentationAttribute attribute in method.GetCustomAttributes(typeof(MethodDocumentationAttribute), false))
                    {
                        Console.ForegroundColor = ConsoleColor.DarkGray;
                        Console.WriteLine(attribute.Description);
                    }
                    Console.ForegroundColor = ConsoleColor.Green;
                    Console.Write(method.Name + "  ");
                    Console.ForegroundColor = ConsoleColor.DarkGray;
                    Console.Write("(");
                    PrintParameters(method);
                    Console.ForegroundColor = ConsoleColor.DarkGray;
                    Console.WriteLine(")");

                    //Console.WriteLine(method.Name + GetParameters(method));
                }
                return;
            }
            var mi = controller.GetType().GetMethod(commandName);
            var parameters = mi.GetParameters();
            var inputParameters = new List<object>();
            foreach (var parameter in parameters)
            {
                string sParamValue = cmd.ParamAfterSwitch(parameter.Name);
                if (!string.IsNullOrEmpty(sParamValue))
                {
                    object paramValue = Convert.ChangeType(sParamValue, parameter.ParameterType);
                    inputParameters.Add(paramValue);
                }
                else
                {
                    Console.WriteLine("Parameter not supplied: " + parameter.Name);
                    Console.WriteLine(mi.Name + GetParameters(mi));
                    return;
                }
                
            }
            mi.Invoke(controller, inputParameters.ToArray());
        }
    }

    public interface ICommandController
    {
    }
}
